//
//  EeSegBar.swift
//  soapp
//
//  Created by zhu xietong on 2017/8/23.
//  Copyright © 2017年 CocoaPods. All rights reserved.
//

import Foundation
import Eelay
public enum EEffect {
    case new(color:UIColor,scale:CGFloat,opacity:CGFloat)
    public var color:UIColor{
        get{
            switch self {
            case .new(color: let color, scale: _, opacity: _):
                return color
            }
        }
    }
    public var scale:CGFloat{
        get{
            switch self {
            case .new(color: _, scale: let scale, opacity: _):
                return scale
            }
        }
    }
    public var opacity:CGFloat{
        get{
            switch self {
            case .new(color: _, scale: _, opacity: let opacity):
                return opacity
            }
        }
    }
    
    open class Button: UIView {
        
        open override var tag: Int{
            didSet{
                self.button.tag = tag
            }
        }
        
        public var effect_select:EEffect{
            return EEffect.new(color: self.select_color, scale: 1, opacity: 1)
        }
        public var effect_normal:EEffect{
            return EEffect.new(color: self.normal_color, scale: 0.9, opacity: 0.9)
        }
        public var title:String = ""{
            didSet{
                isSelected = false
                self.titleL.text = title
            }
        }
        public var titleL = UILabel()
        public var button = UIButton()
        public var select_color = UIColor(shex: "#666")
        public var normal_color = UIColor(shex: "#999")
        
        required public override init(frame: CGRect) {
            super.init(frame: frame)
            
            self.eelay = [
                [titleL,[ee.X.Y]],
                [button,[ee.T.L.B.R]]
            ]
            _ = titleL.ui.center.font14.text("adsffadfrr")
            isSelected = false
            setAttibute()
        }
        
        
        open func setAttibute(){
            
        }
        
        required public init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        
        
//        public func checkProgress(scale:CGFloat,total:Int) {
//            
//            let value = scale * total.cg_floatValue
//            if (value < (self.tag.cg_floatValue + 0.5)) && (value > (self.tag.cg_floatValue - 0.5))
//            {
//                let sc = 1.0 - (abs(value-self.tag.cg_floatValue))/0.5
//                self.checkOpenValue(scale: sc)
//            }
//            
//        }
        
        public var isSelected:Bool = false{
            didSet{
                if isSelected{
                    self.checkOpenValue(scale: 1)
                }
                else{
                    self.checkOpenValue(scale: 0)
                }
            }
        }
        
        public func checkOpenValue(scale:CGFloat,animated:Bool=false) {
            
            let select_percen = scale
            let normal_percen = 1.0 - select_percen
            
            let size_scale = effect_normal.scale*normal_percen + effect_select.scale*select_percen
            let opacity_value = effect_normal.opacity*normal_percen + effect_select.opacity*select_percen
            
            guard let n_colors = effect_normal.color.cgColor.components else{
                titleL.textColor = effect_normal.color
                return
            }
            guard let s_colors = effect_select.color.cgColor.components else{
                titleL.textColor = effect_select.color
                return
            }
            
            let red = n_colors[0] * normal_percen + s_colors[0] * select_percen
            let green = n_colors[1] * normal_percen + s_colors[1] * select_percen
            let blue = n_colors[2] * normal_percen + s_colors[2] * select_percen
            let opacity = n_colors[3] * normal_percen + s_colors[3] * select_percen
            
            let color = UIColor(red: red, green: green, blue: blue, alpha: opacity)
            
            if !animated
            {
                titleL.alpha = opacity_value
                let transform = CGAffineTransform(scaleX: size_scale, y: size_scale)
                titleL.transform = transform.translatedBy(x: 0, y: 0)
                titleL.textColor = color

            }
            else{
                UIView.beginAnimations(nil, context: nil)
                UIView.setAnimationDuration(0.18)
                UIView.setAnimationCurve(.easeInOut)
                titleL.alpha = opacity_value
                let transform = CGAffineTransform(scaleX: size_scale, y: size_scale)
                titleL.transform = transform.translatedBy(x: 0, y: 0)
                titleL.textColor = color
                UIView.commitAnimations()
            }
        }
    }
}



public struct EeSegBarStyle {
    public var indicator_width:CGFloat = 60.co
    public var indicator_height:CGFloat = 2
    public var indicator_color:UIColor = UIColor(shex: "#222")
    
    public var seg_width:CGFloat = 70
    public var normal_color = UIColor(shex: "#888")
    public var select_color = UIColor(shex: "#222")
    public init() {
        
    }
}


public protocol EeSegBarDelegate:NSObjectProtocol {
    func observer(progress:CGFloat,currentIndex:Int,currentScale:CGFloat,nearIndex:Int,nearScale:CGFloat)
    func touched(oldIndex:Int,to:Int)
    func selected(index:Int)
}



public class EeSegBar:UIView {
    public weak var delegate:EeSegBarDelegate?

    
    public var names = [String]()
    public var ui = EeSegBarStyle()
    
    public var indicator = UIView()
    public var segClass:EEffect.Button.Type = EEffect.Button.self
    
    public var progressObserver:(CGFloat)->Void = {_ in}
    
    public var backgroundView:UIView?{
        didSet{
            if let bk = backgroundView
            {
                self.insertSubview(bk, at: 0)
                self.eelay = [
                    [bk,[ee.T.B.L.R]],
                ]
            }
        }
    }
    
    public var __index:Int = 0
    
    public var __needObserverScoll = true

    public var index:Int{

        set{
            if newValue != __index
            {
                self.update(index: newValue)
            }
        }
        get{
            return __index
        }
    }
    
 
    public func updateIndicator(scale:CGFloat) {
        
        if __needObserverScoll
        {
            var _value = scale
            if _value < 0{
                _value = 0
            }
            if _value > 1{
                _value = 1
            }
            let progress = _value * CGFloat(self.names.count)
            
            let index0 = Int(progress)
            let index1 = Int(progress+0.5)
            var nearIndex = max(index0, index1)
            
            let big_half = index1 > index0
            var nearIndex1 = nearIndex + 1
            if big_half{
                nearIndex1 = nearIndex - 1
            }
            
            if nearIndex >= names.count{
                nearIndex = names.count - 1
            }
            if nearIndex < 0{
                nearIndex = 0
            }
            
            
            if nearIndex1 >= names.count{
                nearIndex1 = names.count - 1
            }
            if nearIndex1 < 0{
                nearIndex1 = 0
            }
            
            var current_scale = 1.0 - (progress - CGFloat(nearIndex))
            var near_scale = (progress - CGFloat(nearIndex))
            
            if big_half {
                current_scale = abs(CGFloat(nearIndex1) - progress)
                near_scale = abs(1.0 - current_scale)
            }
            
        
            let currentI = nearIndex
            let nearI = nearIndex1
     
            self.__index = currentI
            
            delegate?.observer(progress: scale, currentIndex: currentI, currentScale: current_scale, nearIndex: nearI, nearScale: near_scale)

    //        print("-=|\(currentI)==|\(nearI)--------------kk|\(current_scale)===|\(near_scale)")
    //        print("=====kk|\(button(with: currentI)!.tag)")
            
            (button(with: currentI) as? EEffect.Button)?.checkOpenValue(scale: current_scale)
            if currentI != nearI
            {
                (button(with: nearI) as? EEffect.Button)?.checkOpenValue(scale: near_scale)
            }
            var point = self.indicator.center
            let p_x_width = self.names.count.cg_floatValue * ui.seg_width
            point.x = (ui.seg_width)/2.0 + p_x_width*scale
            indicator.center = point
        }


    }
    
    func updateIndicatorPosition(index:Int,animated:Bool=false) {        
        if !animated
        {
            let scale = (index.cg_floatValue/self.names.count.cg_floatValue)
            var point = self.indicator.center
            let p_x_width = self.names.count.cg_floatValue * ui.seg_width
            
            point.x = (ui.seg_width)/2.0 + p_x_width*scale
            indicator.center = point
        }
        else{
            let scale = (index.cg_floatValue/self.names.count.cg_floatValue)
            var point = self.indicator.center
            let p_x_width = self.names.count.cg_floatValue * ui.seg_width
            
            point.x = (ui.seg_width)/2.0 + p_x_width*scale
            indicator.center = point
            UIView.beginAnimations(nil, context: nil)
            UIView.setAnimationDuration(0.18)
            UIView.setAnimationCurve(.easeInOut)
            indicator.center = point
            UIView.commitAnimations()
        }
    }
    
    open func button(with index:Int) ->UIView?{
        guard let view = self.viewWithTag(909) else { return nil}
        guard let button = view.viewWithTag(index + 100) else {
            return nil
        }
        return button
        
    }
    
    public func update(index:Int) {
        updateUIWithIndex(index: index)
        self.delegate?.selected(index: index)
    }
    
    func updateUIWithIndex(index:Int) {
        
        
        self.__needObserverScoll = false
        weak var wself = self
        co_delay(delay: 0.4) {
            wself?.__needObserverScoll = true
        }

        delegate?.touched(oldIndex: __index, to: index)
        
        
        
        if abs(__index - index) > 0
        {
            (button(with: __index) as? EEffect.Button)?.checkOpenValue(scale: 0, animated: true)
            (button(with: index) as? EEffect.Button)?.checkOpenValue(scale: 1, animated: true)
        }
        
        
        var point = self.indicator.center
        point.x = (ui.seg_width)/2.0 + index.cg_floatValue * ui.seg_width
        __index = index
        UIView.beginAnimations(nil, context: nil)
        UIView.setAnimationDuration(0.22)
        UIView.setAnimationCurve(.easeInOut)
        indicator.center = point
        UIView.commitAnimations()
        
    }
    
    public var scrollView:UIScrollView?{
        didSet{
            let options: NSKeyValueObservingOptions = [NSKeyValueObservingOptions.new, NSKeyValueObservingOptions.old]
            scrollView?.addObserver(self, forKeyPath: "contentOffset", options: options, context: nil)
        }
    
    }
    
    override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        if let sview = self.scrollView
        {
            if keyPath == "contentOffset" {
                var w = sview.contentSize.width
                if w < 1
                {
                   w = UIScreen.main.bounds.width
                }
                let _scale = sview.contentOffset.x/w
                
                self.updateIndicator(scale: _scale)
                self.progressObserver(_scale)
                
                if sview.contentOffset.x.truncatingRemainder(dividingBy: sview.frame.width) == 0 {
                    let currentIndex = Int(sview.contentOffset.x / sview.frame.width)
                    self.__index = currentIndex
                }

            }
        }
    }

    
    public func loadItems() {
    
        let bts_view = self.viewWithTag(909) ?? UIView()
        bts_view.tag = 909
        addSubview(bts_view)
        
        let vs = bts_view.subviews
        for one in vs{
            one.removeFromSuperview()
        }
        
        
        var pre:UIView?
        for (i,name) in names.enumerated(){
            
            let bt = segClass.init(frame: [0])
            bt.select_color = self.ui.select_color
            bt.normal_color = self.ui.normal_color
          
            
            bt.tag = i + 100
            bt.button.addTarget(self, action: #selector(tapSeg(sender:)), for: .touchUpInside)
            bts_view.eelay = [
                [bt,[ee.T.B,[0,ui.indicator_height/2.0]],Int(ui.seg_width)]
            ]
            
            if let p = pre
            {
                bts_view.eelay = [
                    [bt,[p,ee.R,ee.L],Int(ui.seg_width)]
                ]
            }else{
                bts_view.eelay = [
                    [bt,[ee.L]]
                ]
            }
            
            if i+1 == names.count{
                bts_view.eelay = [
                    [bt,[ee.R]]
                ]
            }
            pre = bt
            bt.title = name
            if self.index == i{
                bt.isSelected = true
            }
            
        
        }
        indicator.removeFromSuperview()
        indicator.backgroundColor = ui.indicator_color
        addSubview(indicator)
        indicator.tag = 10000
        
        indicator.frame = [(ui.seg_width-ui.indicator_width)/2.0,(self.frame.height-ui.indicator_height),ui.indicator_width,ui.indicator_height]
        self.eelay = [
            [bts_view,[ee.X.Y.B]]
        ]
        
    }
    
    
    
    
    @objc public func tapSeg(sender:UIButton) {        
        self.update(index: sender.tag - 100)
    }
    
    override public var intrinsicContentSize: CGSize{
        return self.frame.size
    }
    
    deinit {
        if let scr = scrollView
        {
            scr.removeObserver(self, forKeyPath: "contentOffset")
        }
        

    }
    
}

